package yz.cp.back.admin.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import yz.cp.back.admin.async.AddMessage;
import yz.cp.back.admin.service.UserManage;
import yz.cp.back.admin.vo.SysUserAddVo;
import yz.cp.back.admin.vo.SysUserEditVo;
import yz.cp.back.auth.security.SecUser;
import yz.cp.back.auth.security.SecurityUtils;
import yz.cp.back.common.base.BaseController;
import yz.cp.back.common.constant.CommonConstant;
import yz.cp.back.common.res.ApiResult;
import yz.cp.back.common.service.AESService;
import yz.cp.back.common.vo.SearchVo;
import yz.cp.back.s.entity.*;
import yz.cp.back.s.service.ISysDepartmentHeaderService;
import yz.cp.back.s.service.ISysDepartmentService;
import yz.cp.back.s.service.ISysUserRoleService;
import yz.cp.back.s.service.ISysUserService;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Set;


/**
 * 用户接口
 * @author xukk
 */
@Slf4j
@RestController
@RequestMapping("/web/user")
@CacheConfig(cacheNames = "user")
@Transactional
public class UserController extends BaseController {

    @Autowired
    private ISysUserService userService;
    @Autowired
    private UserManage userManage;

    @Autowired
    private ISysDepartmentService departmentService;

    @Autowired
    private ISysDepartmentHeaderService departmentHeaderService;

    @Autowired
    private ISysUserRoleService userRoleService;
    @Autowired
    private AddMessage addMessage;
    @Autowired
    private AESService aesService;
    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 获取当前登录用户接口
     * @return
     */
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    public ApiResult getUserInfo(){
        SecUser secUser= SecurityUtils.getSecUser();
        SysUser user=userService.findByUsername(secUser.getUsername());
        return renderOk().add(user);
    }

    /**
     * 解锁验证密码
     * @param password
     * @return
     */
    @RequestMapping(value = "/unlock",method = RequestMethod.POST)

    public ApiResult unLock(@RequestParam String password){
        SecUser secUser= SecurityUtils.getSecUser();
        SysUser user=userService.findByUsername(secUser.getUsername());
        if(!new BCryptPasswordEncoder().matches(aesService.decode(password), user.getPassword())){
            return renderError("密码不正确");
        }
        return renderOk("解锁成功");
    }

    /**
     * 修改用户自己资料
     * 用户名密码不会修改 需要username更新缓存
     * @param u
     * @return
     */
    @RequestMapping(value = "/edit",method = RequestMethod.POST)
    @CacheEvict(key = "#u.username")
    public ApiResult editOwn(@ModelAttribute SysUser u){
        SecUser secUser= SecurityUtils.getSecUser();
        SysUser old=userService.findByUsername(secUser.getUsername());
        u.setId(old.getId());
        u.setUsername(null);
        u.setPassword(null);
        userService.updateById(u);
        return renderOk("修改成功");
    }

    /**
     * 管理员修改资料
     * 需要通过id获取原用户信息 需要username更新缓存
     * @param u
     * @param roles
     * @return
     */
    @RequestMapping(value = "/admin/edit",method = RequestMethod.POST)
    @CacheEvict(key = "#u.username")
    public ApiResult edit(@ModelAttribute SysUserEditVo vo,
                          @RequestParam(required = false) String[] roles){
        SysUser u=beanMapper.map(vo,SysUser.class);
        SysUser old = userService.getById(u.getId());
        //若修改了用户名
        if(!old.getUsername().equals(u.getUsername())){
            //若修改用户名删除原用户名缓存
            redisTemplate.delete("user::"+old.getUsername());
            //判断新用户名是否存在
            if(userService.findByUsername(u.getUsername())!=null){
                return renderError("该用户名已存在");
            }
            //删除缓存
            redisTemplate.delete("user::"+u.getUsername());
        }

        // 若修改了手机和邮箱判断是否唯一
        if(!old.getMobile().equals(u.getMobile())&&userService.findByMobile(u.getMobile())!=null){
            return renderError("该手机号已绑定其他账户");
        }
        if(!old.getEmail().equals(u.getEmail())&&userService.findByMobile(u.getEmail())!=null){
            return renderError("该邮箱已绑定其他账户");
        }
        u.setId(old.getId());
        u.setPassword(null);
        userService.updateById(u);
        //删除该用户角色
        userRoleService.deleteByUserId(u.getId());
        if(roles!=null&&roles.length>0){
            //新角色
            for(String roleId : roles){
                SysUserRole ur = new SysUserRole();
                ur.setRoleId(roleId);
                ur.setUserId(u.getId());
                userRoleService.save(ur);
            }
        }
        //手动删除缓存
        redisTemplate.delete("userRole::"+u.getId());
        redisTemplate.delete("userRole::depIds:"+u.getId());
        return renderOk("修改成功");
    }

    /**
     * 修改密码
     * @param password
     * @param newPass
     * @param passStrength
     * @return
     */
    @RequestMapping(value = "/modifyPass",method = RequestMethod.POST)
    public ApiResult modifyPass( @RequestParam String password,
                                 @RequestParam String newPass,
                                 @RequestParam String passStrength){

        SecUser secUser= SecurityUtils.getSecUser();
        SysUser user=userService.findByUsername(secUser.getUsername());
        password=aesService.decode(password);
        newPass=aesService.decode(newPass);
        if(!new BCryptPasswordEncoder().matches(password, user.getPassword())){
            return renderError("旧密码不正确");
        }
        SysUser updateUser=new SysUser();
        String newEncryptPass= new BCryptPasswordEncoder().encode(newPass);
        updateUser.setPassword(newEncryptPass);
        updateUser.setPassStrength(passStrength);
        updateUser.setId(user.getId());
        userService.updateById(updateUser);

        //手动更新缓存
        redisTemplate.delete("user::"+user.getUsername());

        return renderOk("修改密码成功");
    }

    /**
     * 多条件分页获取用户列表
     * @param user
     * @param searchVo
     * @param pageVo
     * @return
     */
    @RequestMapping(value = "/getByCondition",method = RequestMethod.GET)
    public ApiResult  getByCondition(@ModelAttribute SysUser user,
                                     @ModelAttribute SearchVo searchVo,
                                     @PageableDefault Pageable pageable
    ){

        IPage<SysUser> page=userManage.findByCondition(user,searchVo,pageable);
        for(SysUser u: page.getRecords()){
            // 关联部门
            if(StringUtils.isNotBlank(u.getDepartmentId())){
                SysDepartment department = departmentService.getById(u.getDepartmentId());
                u.setDepartmentTitle(department.getTitle());
            }
            // 关联角色
            List<SysRole> list = userRoleService.findByUserId(u.getId());
            u.setRoles(list);
        }
        return renderOk().add(page);
    }

    /**
     * 多条件分页获取用户列表
     * @param departmentId
     * @return
     */
    @RequestMapping(value = "/getByDepartmentId/{departmentId}",method = RequestMethod.GET)
    public ApiResult getByCondition(@PathVariable String departmentId){
        List<SysUser> list= userService.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getDepartmentId,departmentId));
        list.forEach(u ->
                u.setPassword(null)
        );
        return renderOk().add(list);
    }

    /**
     * 通过用户名搜索用户
     * @param username
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(value = "/searchByName/{username}",method = RequestMethod.GET)
    public ApiResult searchByName(@PathVariable String username) throws UnsupportedEncodingException {
        return renderOk().add(userService.list(new QueryWrapper<SysUser>().lambda()
                .eq(SysUser::getStatus,CommonConstant.STATUS_NORMAL)
                .like(SysUser::getUsername, SqlLike.DEFAULT)));
    }


    /**
     * 添加用户
     * @param u
     * @param roles
     * @return
     */
    @RequestMapping(value = "/admin/add",method = RequestMethod.POST)
    public ApiResult regeist(@ModelAttribute SysUserAddVo vo,
                            @RequestParam(required = false) String[] roles){
        SysUser u=beanMapper.map(vo,SysUser.class);
        if(StringUtils.isAnyBlank(u.getUsername(),u.getPassword())){
            return renderError("缺少必需表单字段");
        }

        if(userService.count(new QueryWrapper<SysUser>().lambda().eq(SysUser::getUsername,u.getUpdateTime()))>0){
            return renderError("该用户名已被注册");
        }
        //删除缓存
        redisTemplate.delete("user::"+u.getUsername());

        String encryptPass = new BCryptPasswordEncoder().encode(aesService.decode(u.getPassword()));
        u.setPassword(encryptPass);
        userService.save(u);
        if(u==null||StringUtils.isBlank(u.getId())){
            return renderError("添加失败");
        }
        if(roles!=null&&roles.length>0){
            //添加角色
            for(String roleId : roles){
                SysUserRole ur = new SysUserRole();
                ur.setUserId(u.getId());
                ur.setRoleId(roleId);
                userRoleService.save(ur);
            }
        }
        // 发送创建账号消息
        addMessage.addSendMessage(u.getId());

        return renderOk("添加成功");
    }

    /**
     * 后台禁用用户
     * @param userId
     * @return
     */
    @RequestMapping(value = "/admin/disable/{userId}",method = RequestMethod.POST)
    public ApiResult disable(@PathVariable String userId){
        SysUser user = userService.getById(userId);
        if(user==null){
            return renderError("通过userId获取用户失败");
        }
        user.setStatus(CommonConstant.USER_STATUS_LOCK);
        SysUser sysUser=new SysUser();
        sysUser.setId(userId);
        sysUser.setStatus(CommonConstant.USER_STATUS_LOCK);
        userService.updateById(sysUser);
        //手动更新缓存
        redisTemplate.delete("user::"+user.getUsername());
        return renderOk("操作成功");
    }

    /**
     * 后台启用用户
     * @param userId
     * @return
     */
    @RequestMapping(value = "/admin/enable/{userId}",method = RequestMethod.POST)
    public ApiResult enable( @PathVariable String userId){
        SysUser user = userService.getById(userId);
        if(user==null){
            return renderError("通过userId获取用户失败");
        }
        SysUser sysUser=new SysUser();
        sysUser.setId(userId);
        sysUser.setStatus(CommonConstant.USER_STATUS_NORMAL);
        userService.updateById(sysUser);
        //手动更新缓存
        redisTemplate.delete("user::"+user.getUsername());
        return renderOk("操作成功");
    }

    /**
     * 批量通过ids删除
     * @param ids
     * @return
     */
    @DeleteMapping(value = "/delByIds/{ids}")
    public ApiResult delAllByIds(@PathVariable String[] ids){
        for(String id:ids){
            SysUser u = userService.getById(id);
            //删除相关缓存
            redisTemplate.delete("user::" + u.getUsername());
            redisTemplate.delete("userRole::" + u.getId());
            redisTemplate.delete("userRole::depIds:" + u.getId());
            redisTemplate.delete("permission::userMenuList:" + u.getId());
            Set<String> keys = redisTemplate.keys("department::*");
            redisTemplate.delete(keys);
            userService.removeById(id);
            //删除关联角色
            userRoleService.remove(new QueryWrapper<SysUserRole>()
                    .lambda().eq(SysUserRole::getUserId,id));
            // 删除关联部门负责人
            departmentHeaderService.remove(new QueryWrapper<SysDepartmentHeader>()
                    .lambda().eq(SysDepartmentHeader::getUserId,id));
        }
        return renderOk("批量通过id删除数据成功");
    }

//    @RequestMapping(value = "/importData",method = RequestMethod.POST)
//    @ApiOperation(value = "导入用户数据")
//    public Result<Object> importData(@RequestBody List<User> users){
//
//        List<Integer> errors = new ArrayList<>();
//        List<String> reasons = new ArrayList<>();
//        int count = 0;
//        for(User u: users){
//            count++;
//            // 验证用户名密码不为空
//            if(StrUtil.isBlank(u.getUsername())||StrUtil.isBlank(u.getPassword())){
//                errors.add(count);
//                reasons.add("用户名或密码为空");
//                continue;
//            }
//            // 验证用户名唯一
//            if(userService.findByUsername(u.getUsername())!=null){
//                errors.add(count);
//                reasons.add("用户名已存在");
//                continue;
//            }
//            //删除缓存
//            redisTemplate.delete("user::"+u.getUsername());
//            // 加密密码
//            u.setPassword(new BCryptPasswordEncoder().encode(u.getPassword()));
//            // 验证部门id正确性
//            if(StrUtil.isNotBlank(u.getDepartmentId())){
//                try {
//                    Department d = departmentService.get(u.getDepartmentId());
//                    log.info(d.toString());
//                }catch (Exception e){
//                    errors.add(count);
//                    reasons.add("部门id不存在");
//                    continue;
//                }
//            }
//            if(u.getStatus()==null){
//                u.setStatus(CommonConstant.USER_STATUS_NORMAL);
//            }
//            // 分配默认角色
//            if(u.getDefaultRole()!=null&&u.getDefaultRole()==1){
//                List<Role> roleList = roleService.findByDefaultRole(true);
//                if(roleList!=null&&roleList.size()>0){
//                    for(Role role : roleList){
//                        UserRole ur = new UserRole();
//                        ur.setUserId(u.getId());
//                        ur.setRoleId(role.getId());
//                        iUserRoleService.insert(ur);
//                    }
//                }
//            }
//            // 保存数据
//            userService.save(u);
//        }
//        int successCount = users.size() - errors.size();
//        String successMessage = "全部导入成功，共计 " + successCount + " 条数据";
//        String failMessage = "导入成功 " + successCount + " 条，失败 " + errors.size() + " 条数据。<br>" +
//                "第 " + errors.toString() + " 行数据导入出错，错误原因分别为：<br>" + reasons.toString();
//        String message = "";
//        if(errors.size()==0){
//            message = successMessage;
//        }else{
//            message = failMessage;
//        }
//        return new ResultUtil<Object>().setSuccessMsg(message);
//    }
}
